package cache

import (
	"math"
	"time"
)

type ExpiryManager struct {
	cache Cache
}

func NewExpiryManager(cache Cache) *ExpiryManager {
	return &ExpiryManager{cache: cache}
}

/*
在 Go 中，内部函数（也被称为闭包）可以访问其外部函数的变量。这是因为它们共享相同的词法作用域。在你的代码中，minExpiration 是在 deleteExpired 函数的作用域内定义的，所以 Foreach 的参数函数（即闭包）可以访问和修改它。
在这个例子中，每次调用参数函数时，都会检查当前条目的 expiryAt 是否小于 minExpiration，如果是，则更新 minExpiration。这种操作是合法的，因为参数函数可以访问并修改其外部作用域的变量。
这一特性使得闭包在处理数据集合时非常有用，因为它们可以累积或记录信息，而不需要明确地将结果传回主函数。
*/

func (manager *ExpiryManager) deleteExpired() time.Duration {
	var minExpiration int64 = math.MaxInt64

	manager.cache.ForeachExpired(func(key string, item *Item) {
		now := time.Now().Unix()
		if item.expiryAt <= now {
			_ = manager.cache.Delete(item.key)
		} else if item.expiryAt < minExpiration {
			minExpiration = item.expiryAt
		}
	})

	// Check in case there were no non-expired items.
	if minExpiration == math.MaxInt64 {
		return 0
	}

	// Return the duration until the soonest expiryAt.
	/*
		在Go语言的time.Unix(sec int64, nsec int64)函数中，第一个参数sec代表自1970年1月1日UTC零时以来的秒数，第二个参数nsec代表额外的纳秒数。
		在time.Unix(minExpiration, 0)中，minExpiration是秒数，而0表示没有额外的纳秒数。
		所以，这个函数调用会根据给定的秒数返回对应的Time值（精确到秒，没有纳秒级别的更细粒度）
	*/
	return time.Until(time.Unix(minExpiration, 0))
}
